home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / misc / emu / QDOS2.lha / QLsource / src / L_QDOS.c next >
C/C++ Source or Header  |  1996-02-06  |  10KB  |  538 lines

  1. ;/*
  2. A68k sub.asm
  3. dcc -o L_QDOS L_QDOS.c -l hardware SUB.o
  4. quit
  5. */
  6. /* L_QDOS loads and runs QDOS */
  7.  
  8. #include <exec/exec.h>
  9. #include <exec/libraries.h>
  10. #include <dos/dos.h>
  11. #include <intuition/intuition.h>
  12. #include <workbench/workbench.h>
  13. #include <stdio.h>
  14. #include <hardware/cia.h>
  15.  
  16. #define MAXROMS 16
  17.  
  18. extern struct ExecBase *SysBase;
  19. extern __far struct CIA ciaa, ciab;
  20.  
  21. typedef struct List         LIST;
  22. typedef struct Node         NODE;
  23. typedef struct MemHeader MEMHEADER;
  24. typedef struct MemChunk  MEMCHUNK;
  25.  
  26. extern int sub(),dummy();
  27. extern int subtoclear();
  28.  
  29. long ql_lomem,ql_himem,ql_ssp,ql_var,rom_lomem;
  30. int sflag,mflag,cflag,ccount,rflag,rcount,dflag;
  31. long qldate;
  32.  
  33. struct
  34. {
  35.   long day;
  36.   long min;
  37.   long tick;
  38. } date;
  39.  
  40. struct rominfo
  41. {
  42.   char *name;
  43.   VOID *fp;
  44.   long len;
  45.   long rlen;
  46. };
  47.  
  48. struct memrange
  49. {
  50.   long lomem;
  51.   long himem;
  52. };
  53.  
  54. struct memrange *toclear;
  55. struct rominfo rom[MAXROMS];
  56.  
  57. typedef struct CommandLineInterface CLI;
  58. typedef struct Process PROCESS;
  59.  
  60. CLI      *cli;
  61. PROCESS *proc;
  62.  
  63. extern int    _start_();
  64. extern int    _realstart_();
  65.  
  66. extern long _Detached_,   /* are we detached?    */
  67.                 _WorkBench_,  /* are we on the WB?    */
  68.                 _CLI_,          /* are we on the CLI? */
  69.                 _Process_;      /* are we a process?    */
  70. #if 1
  71. /* how to change the default console (if it's used) */
  72. char _DefaultConsole[] =
  73.          "CON:0/12/320/72/L_QDOS 2.03, loading QDOS...";
  74. #endif
  75.  
  76. char VERSTAG[] = "\0$VER: L_QDOS 2.03";
  77.  
  78. shutdown(s) char *s;
  79. {
  80.   printf("%ls\n",s);
  81.   if(_WorkBench_ || _Detached_)
  82.   {
  83.      Delay(500);
  84.   }
  85.   exit(0);
  86. }
  87.  
  88. usage()
  89. {
  90.   shutdown("L_QDOS v2.03\n\n"
  91.               "usage:\tL_QDOS [-r]\n"
  92.                       "\t       [-q<QDOS rom>]\n"
  93.                       "\t       [-p<MAIN rom>]\n"
  94.                       "\t       [-m<lomem><+len|-himem>]\n"
  95.                       "\t       [<OTHER roms>...]\n");
  96. }
  97.  
  98. warning(s) char *s;
  99. {
  100.   printf("%ls\n",s);
  101. }
  102.  
  103. char *
  104. getnum(p,np) char *p; long *np;
  105. { long n,h;
  106.   char c;
  107.   c=*p++;
  108.   n=0;
  109.   if(c!='$')
  110.   {
  111.      while(isdigit(c))
  112.      {
  113.         h=c-48;
  114.         n=n*10+h;
  115.         c=*p++;
  116.      }
  117.   }
  118.   else
  119.   {
  120.      c=*p++;
  121.      while(isxdigit(c))
  122.      {
  123.         h=(c<58?c-48:(c<96?c-55:c-87));
  124.         n=n*16+h;
  125.         c=*p++;
  126.      }
  127.   }
  128.   *np=n;
  129.   return --p;
  130. }
  131.  
  132. doflags(p) char *p;
  133. {
  134.   long num;
  135.   while(*p!=0)
  136.   { switch(toupper(*p++))
  137.      {
  138.      case 'D':
  139.         dflag=1;
  140.         break;
  141.      case 'R':
  142.         rflag=1;
  143.         break;
  144.      case 'Q':
  145.         rom[0].name=p;
  146.         while (*p!=0)
  147.           p++;
  148.         break;
  149.      case 'P':
  150.         rom[1].name=p;
  151.         while (*p!=0)
  152.           p++;
  153.         break;
  154.      case 'M':
  155.         while(*p!=0)
  156.         { p=getnum(p,&num);
  157.           switch(*p)
  158.           {
  159.           case '+':
  160.              mflag=1;
  161.              ql_var=num;
  162.              break;
  163.           case '-':
  164.              mflag=2;
  165.              ql_var=num;
  166.              break;
  167.           case 0:
  168.              switch(mflag)
  169.              {
  170.              case 1:
  171.                 ql_himem=ql_var+num;
  172.                 break;
  173.              case 2:
  174.                 ql_himem=num;
  175.                 break;
  176.              default:
  177.                 usage();
  178.              }
  179.              break;
  180.           default:
  181.              usage();
  182.           }
  183.           if(*p!=0)
  184.              p++;
  185.         }
  186.         break;
  187.      default:
  188.         usage();
  189.      }
  190.   }
  191. }
  192.  
  193. int
  194. findrom(rom) struct rominfo *rom;
  195. {
  196.   long len;
  197.   VOID *f;
  198.   char temp[80];
  199.   f = fopen(rom->name,"r");
  200.   if(f == 0)
  201.   { strcpy(temp,rom->name);
  202.      strcat(temp," not available");
  203.      warning(temp);
  204.      len=0;
  205.   }
  206.   else
  207.   { fseek(f,0,2);
  208.      len=ftell(f);
  209.      fseek(f,0,0);
  210.   }
  211.   rom->fp = f;
  212.   rom->len=len;
  213.   len+=255;
  214.   len&=-256;
  215.   rom->rlen=len;
  216.   return len;
  217. }
  218.  
  219. main(argc,argv)
  220. int argc;
  221. char **argv;
  222. {
  223.   int i,j,n;
  224.   long olddir;
  225.   long rom_tot,rom_len,len,rom_dst,sub_len,sub_dst;
  226.   char *p,*qp,*cp,**av;
  227.  
  228.   MEMHEADER *mh;
  229.   long mh_lower, mh_upper;
  230.  
  231.   _DetachFromCLI();         /* Does just that. (Or nothing if */
  232.                                  /* run from the WorkBench).          */
  233.  
  234.   _RunOnWorkBench();      /* Indicates this program should  */
  235.                                  /* continue and will run properly */
  236.                                  /* if started from the WorkBench. */
  237.                                  /* Well, you say it will.           */
  238.  
  239.   _ToolTypeArgs();         /* Means move tooltype array from */
  240.                                  /* .info file to argc,argv.          */
  241.  
  242.   _OpenDefaultConsole(); /* Need this to use printf's etc  */
  243.                                  /* when starting from WorkBench   */
  244.                                  /* or if you've detached.         */
  245.                                  /* (You won't need it if you're   */
  246.                                  /* only using intuition stuff).   */
  247.                                  /* Does nothing if you're running */
  248.                                  /* on the CLI/Shell.                  */
  249.  
  250.   toclear=(struct memrange *)subtoclear;
  251.  
  252.   mflag=sflag=cflag=ccount=rflag=dflag=0;
  253.   rcount=2;
  254.   ql_lomem=rom_lomem=0;
  255.   ql_himem=0x10000000;
  256.   ql_ssp=0x28480;
  257.   ql_var=0x28000;
  258.  
  259.   for(i=1;i<argc;i++)
  260.   {
  261. /*  printf("arg %ld = %ls\n",i,argv[i]); */
  262.      if(argv[i][0]=='?')
  263.         usage();
  264.      if(argv[i][0]=='-')
  265.         doflags(argv[i]+1);
  266.      else
  267.      {
  268.         if(rcount<MAXROMS)
  269.         { rom[rcount].name=argv[i];
  270.           rcount++;
  271.         }
  272.         else
  273.           shutdown("too many roms");
  274.      }
  275.   }
  276.   if(dflag!=0)
  277.      warning("...now in debug mode");
  278.  
  279.   if(dflag!=0)
  280.      printf("to clear structure=$%lx $%lx\n\n",(long)toclear,(long)subtoclear);
  281.  
  282.   ccount=0;
  283.   for (mh  = (MEMHEADER *)GetHead((LIST *)&SysBase->MemList);
  284.          mh != 0;
  285.          mh  = (MEMHEADER *)GetSucc((NODE *)mh))
  286.   {
  287.      mh_lower=mh->mh_Lower;
  288.      mh_upper=mh->mh_Upper;
  289.      if (((long)mh+sizeof(MEMHEADER))=mh_lower)
  290.         mh_lower=(long)mh;
  291.  
  292.      if (ccount!=0)
  293.         for (i=0;i<ccount;i++)
  294.           if (mh_lower<toclear[i].lomem)
  295.           {
  296.              n=mh_lower;mh_lower=toclear[i].lomem;toclear[i].lomem=n;
  297.              n=mh_upper;mh_upper=toclear[i].himem;toclear[i].himem=n;
  298.           }
  299.  
  300.      toclear[ccount].lomem=mh_lower;
  301.      toclear[ccount].himem=mh_upper;
  302.      ccount++;
  303.  
  304.   }
  305.  
  306.   i=0;
  307.   while ((i<ccount)&(ql_var>toclear[i].himem))
  308.      i++;
  309.  
  310.   if (i<ccount)
  311.      if (ql_var<toclear[i].lomem)
  312.         ql_var=toclear[i].lomem;
  313.  
  314.   i=ccount-1;
  315.   while ((i>=0)&(ql_himem<toclear[i].lomem))
  316.      i--;
  317.  
  318.   if (i>=0)
  319.      if (ql_himem>toclear[i].himem)
  320.         ql_himem=toclear[i].himem;
  321.  
  322.   if (ql_himem>0x1000000)
  323.      if (ql_var<toclear[ccount-1].lomem)
  324.         ql_var=toclear[ccount-1].lomem;
  325.  
  326.   if(dflag!=0)
  327.   {
  328.      for (i=0;i<ccount;i++)
  329.         printf("$%08lX $%08lX \n",toclear[i].lomem,toclear[i].himem);
  330.   }
  331.  
  332.   if(rom[0].name==0)
  333.      rom[0].name="QLboot:ROMs/SYS_cde";
  334.   if(rom[1].name==0)
  335.      rom[1].name="QLboot:ROMs/MAIN_cde";
  336.   rom_tot=0;
  337.   for(i=0;i==0 || i<rcount;i++)
  338.   { len=findrom(&rom[i]);
  339.      if((len==0)&&(i<2))
  340.         shutdown("sorry but I can't load QDOS");
  341.      if(dflag!=0)
  342.         printf("%ls\n",rom[i].name);
  343.  
  344.      rom_tot+=len;
  345.   }
  346.  
  347.   if(dflag!=0)
  348.      printf("total space req=$%lx/%ld\n",rom_tot,rom_tot);
  349.  
  350.   if(rom_tot!=0)
  351.   {
  352.      p = (char *)malloc(rom_tot);
  353.      if(p==0)
  354.         shutdown("no memory");
  355.      qp=p;
  356.      for(i=0;i<rcount;i++)
  357.      { if(rom[i].len!=0)
  358.         { fread(p,rom[i].len,1,rom[i].fp);
  359.           p+=rom[i].rlen;
  360.         }
  361.      }
  362.   }
  363.  
  364.   rom_len=rom_tot-rom[0].rlen-rom[1].rlen;
  365.  
  366.   if(dflag!=0)
  367.   { printf("QDOS and ROMS source=$%lx\n",qp);
  368.      printf("QDOS len=$%lx\n",rom[0].rlen);
  369.      printf("MAIN len=$%lx\n",rom[1].rlen);
  370.      printf("ROMs len=$%lx\n\n",rom_len);
  371.   }
  372.  
  373.   DateStamp(&date);
  374.   qldate=date.day+365*17+4;
  375.   qldate=qldate*(24*60*60/8);
  376.   qldate<<=3;
  377.   qldate+=(date.min*60);
  378.   qldate+=(date.tick/50);
  379.   if(dflag!=0)
  380.   { printf("days=%ld mins=%ld ticks=%ld\n",date.day,date.min,date.tick);
  381.      printf("qldate=$%08lx\n",qldate);
  382.   }
  383.  
  384.   ql_var=(ql_var+0x7FFF)&(-0x8000);
  385.   ql_himem=ql_himem&(-0x200);
  386.  
  387.   rom_dst=(ql_himem-rom_len)&(-0x200);
  388.   sub_len=(long)dummy-(long)sub;
  389.   sub_dst=((ql_himem-rom_tot)&(-0x200))-sub_len;
  390.  
  391.   ql_himem=rom_dst;
  392.   if(rflag!=0)
  393.      if(ql_himem>0x200000)
  394.         ql_himem=ql_himem-rom[0].rlen+0x600;
  395.  
  396.   if(dflag!=0)
  397.      printf("rom_dst=$%lx\n",rom_dst);
  398.  
  399.   if(ql_var<0x28000)
  400.      ql_var=0x28000;
  401.  
  402.   ql_ssp=ql_var+0x480;
  403.   ql_lomem=ql_ssp;
  404.  
  405.   if(dflag!=0)
  406.      printf("lomem=$%lx himem=$%lx\n\n",ql_lomem,ql_himem);
  407.  
  408.  
  409.   if(ql_lomem>=ql_himem)
  410.      shutdown("bad value for memory range\n...might be out of memory\n ");
  411.  
  412. check_dst:
  413.   if(((long)qp <= sub_dst) && ((long)qp + rom_tot > sub_dst))
  414.      sub_dst=qp-sub_len;
  415.   if(((long)sub<=sub_dst)&&((long)sub+sub_len>sub_dst))
  416.   { sub_dst=(long)sub-sub_len;
  417.      goto check_dst;
  418.   }
  419.   if(dflag!=0)
  420.      printf("sub src=$%lx sub dst=$%lx sub len=$%lx\n\n"
  421.               ,(long)sub,sub_dst,sub_len);
  422.  
  423.   i=0;
  424.   while(i<ccount)
  425.   {
  426.      if(toclear[i].lomem<rom[0].rlen)
  427.      { if(toclear[i].himem>rom[0].rlen)
  428.           toclear[i].lomem=rom[0].rlen;
  429.         else
  430.           goto removerange;
  431.      }
  432.  
  433.      if(toclear[i].lomem<0x1c000)
  434.      { if(toclear[i].himem>0x1c000)
  435.         { if(toclear[i].himem>(0x1c000+rom[1].rlen))
  436.           { if(ccount<8)
  437.              { toclear[ccount].lomem=0x1c000+rom[1].rlen;
  438.                 toclear[ccount].himem=toclear[i].himem;
  439.                 ccount++;
  440.              }
  441.              else
  442.                 shutdown("range too complex");
  443.              }
  444.  
  445.           toclear[i].himem=0x1c000;
  446.         }
  447.      }
  448.  
  449.      if(toclear[i].lomem<sub_dst)
  450.      { if(toclear[i].himem>sub_dst)
  451.         { if(toclear[i].himem>(sub_dst+sub_len))
  452.           { if(ccount<8)
  453.              { toclear[ccount].lomem=sub_dst+sub_len;
  454.                 toclear[ccount].himem=toclear[i].himem;
  455.                 ccount++;
  456.              }
  457.              else
  458.                 shutdown("range too complex");
  459.              }
  460.  
  461.           toclear[i].himem=sub_dst;
  462.         }
  463.      }
  464.  
  465.      if(toclear[i].lomem<rom_dst)
  466.      { if(toclear[i].himem>rom_dst)
  467.         { if(toclear[i].himem>(rom_dst+rom_len))
  468.           { if(ccount<8)
  469.              { toclear[ccount].lomem=rom_dst+rom_len;
  470.                 toclear[ccount].himem=toclear[i].himem;
  471.                 ccount++;
  472.              }
  473.              else
  474.                 shutdown("range too complex");
  475.              }
  476.  
  477.           toclear[i].himem=rom_dst;
  478.         }
  479.      }
  480.  
  481.      if(toclear[i].lomem<ql_himem)
  482.      { if(toclear[i].himem>ql_himem)
  483.           toclear[i].himem=ql_himem;
  484.      }
  485.      else
  486.         goto removerange;
  487.  
  488.      if(toclear[i].lomem==toclear[i].himem)
  489.         goto removerange;
  490.  
  491.      i++;
  492.      goto endwhile;
  493.  
  494.      removerange:
  495.      ccount--;
  496.      toclear[i].lomem=toclear[ccount].lomem;
  497.      toclear[i].himem=toclear[ccount].himem;
  498.      endwhile:
  499.   }
  500.   toclear[ccount].lomem=0;
  501.   toclear[ccount].himem=0;
  502.  
  503.   if(dflag!=0)
  504.   { i=0;
  505.      while(i<ccount)
  506.      { printf("range: lomem=$%lx himem=%lx\n"
  507.                  ,toclear[i].lomem,toclear[i].himem);
  508.         i++;
  509.      }
  510.   }
  511.  
  512.   if(dflag!=0)
  513.   { printf("vars=$%lx ssp=$%lx\n\n",ql_var,ql_ssp);
  514.      shutdown("quitting L_QDOS...\n");
  515.   }
  516.  
  517.   Forbid();
  518.   Disable();
  519.   OwnBlitter();
  520.   while(WaitBlit());
  521.  
  522.   if(((struct Library *)SysBase)->lib_Version>=37)
  523.     CacheControl(0,CACRF_EnableI|CACRF_EnableD|CACRF_IBE|CACRF_DBE);
  524.  
  525. /* deselect all drives                                */
  526.   ciab.ciaprb|=CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
  527. /* motor signal (off)                                */
  528.   ciab.ciaprb|=CIAF_DSKMOTOR;
  529. /* select all drives (thus, switch them off) */
  530.   ciab.ciaprb&=~(CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3);
  531. /* deselect drives again (well, why not?)     */
  532.   ciab.ciaprb|=CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
  533.  
  534.   sub(sub_dst,ql_lomem,ql_himem,rom_dst,qp,
  535.         rom[0].rlen,rom_len,rom[1].rlen,ql_ssp,qldate);
  536. }
  537.  
  538.